接下來我們今天來介紹不同環境下要如何處理 Error 以及我們需要處裡哪些 Error :
在 Development 環境中:
盡可能方便我們追蹤錯誤,所以會傾向 Error message 越詳細越好。
例如: 可以知道是哪個地方發生錯誤,路徑是什麼?
範例:
const sendDevelopmentError = (err, res) => {
res.status(err.statusCode).json({
status: err.status,
error: err,
message: err.message,
stack: err.stack
})
}
解說:
可以看到在以上範例,我們沒有傳送 error & stack。
在 Staging / Production 環境中:
範例:
const sendProdctionError = (err, res) => {
// 如果是操作型的 Error,傳送他
if (err.isOperational) {
res.status(err.statusCode).json({
status: err.status,
message: err.message
})
} else {
// log error
console.error('Error: ', err);
// 若非操作型 Error,傳送比較 general 的 error message
res.status(500).json({
status: 'error',
message: 'Something went wrong'
})
}
res.status(err.statusCode).json({
status: err.status,
message: err.message,
})
}
解說:
可以看到在以上範例,我們沒有傳送 error & stack。
最後,在 ErrorController 中判斷 env development or production:
module.exports = (err, req, res, next) => {
err.statusCode = err.statusCode || 500;
err.status = err.status || 'error';
if (process.env.NODE_ENV === 'development') {
sendDevelopmentError(err, res);
} else if (process.env.NODE_ENV === 'prodcution') {
sendProductionError(err, res);
}
}
還記得我們之前介紹的 Error 種類大致分為哪幾種嗎?
有 Operational Error 以及 Programming Error。
在處理 Operational Error 時,需要考慮我們自己處理了哪些 Operational Error ? 而哪些 Operational Error 目前是沒有被標記成 Operational 的呢 ?
在此處,除了有關沒有資料的 Error 外,我們還需要考慮與 "資料庫" 相關的 Error ~
我們是使用 MongoDB ,MongoDB 有很多種不同的 Error,可以參考:
(圖片來源: https://mongoosejs.com/docs/5.x/docs/api/error.html)
可以根據自己的需求,去處理有關的 Error:
假設我們要處理 CastError:
範例:
const handleCastErrorInDB = err => {
const message = `Invalid ${err.path} : ${err.value}`;
// 400 意味著錯誤請求
return new AppError(message, 400);
}
在先前判斷環境的入口,我們可以加上以下 error 來處理 DB 的 CastError:
let error = { ...err };
if (error.name === 'CastError') error = handleCastErrorInDB(error);
在同步的程式中,可能會出現 Uncaught Exception,例如: 一些 Programming Error,像是在某處讀取了 undefined 的元素。
在 Node.js 中,它在 process 中就會捕獲發現的 uncaught Exception,所以我們可以透過監聽他並進行處理:
process.on('uncaughtException', err => {
console.log(err.name, err.message);
console.log('Unhandled Exception and we need to shut down.');
server.close(() => {
process.exit(1);
})
});
非同步程式碼中,也可能會出現一些我們之前沒有處理過的例外狀況,例如: MongoDB 不能連線。
在 Node.js 中,它在 process 中就會捕獲發現的 unhandled Rejection,所以我們可以透過監聽他並進行處理:
process.on('unhandledRejection', err => {
console.log(err.name, err.message);
console.log('Unhandled Rejection and we need to shut down.');
server.close(() => {
process.exit(1);
})
});
今天的介紹就到這邊啦 ~ 明天會繼續進行其他的介紹
Node.js, Express, MongoDB & More: The Complete Bootcamp 2023
https://www.udemy.com/course/nodejs-express-mongodb-bootcamp/learn/lecture/15065226#overview
NodeJS / Express 處理 Uncaught Exception 或是非同步的裡的 Unhandled Rejection
https://elton-lau.medium.com/nodejs-express-%E8%99%95%E7%90%86-uncaught-exception-%E6%88%96%E6%98%AF%E9%9D%9E%E5%90%8C%E6%AD%A5%E7%9A%84%E8%A3%A1%E7%9A%84-unhandled-rejection-48f364ebeb4e